<?
// Functions related to forms
// Written by John Shepherd, April 2004
// Updated by John Shepherd, June 2006
// Assumes that "lib/defs.php" already included


# startForm:
# - returns HTML to start off a form
# - url: URL of form processing script (mandatory)
# - check: name of JavaScript function to check inputs (optional)
# - name: name of the form in the DOM for this page
# - target: alternative window in which to pop-up processing script

function startForm($url="",$name="",$check="",$target="")
{
	$action = ($url != "") ? " action='$url'" : "";
	$name   = ($name != "") ? " name='$name'" : "";
	$check  = ($check != "") ? " onSubmit='$check'" : "";
	$target = ($target != "") ? " target='$target'" : "";
	return "<form method='post'$action$name$target$check>\n";
}

# endForm:
# - returns HTML to finish off a form

function endForm() { return "</form>\n"; }

function hidden($name,$value) {
	$value = htmlVal($value);
	return "<input type='hidden' id='$name' name='$name' value='$value'>\n";
}

function inputText($name,$value="",$size=null,$autoclear="")
{
	$value = htmlVal($value);
	$s = def($size) ? " size='$size'" : "";
	if (!def($autoclear))
		$a = "";
	else
		$a = " onfocus=\"if(this.value=='$autoclear'){this.value=''}\"";
	return "<input type='text' name='$name' value='$value'$s$a>";
}

function inputPassword($name,$value,$size="")
{
	$value = htmlVal($value);
	if ($size == "") $size = 20;
	return "<input type='password' name='$name' value='$value' size='$size'>";
}

function inputTextArea($name,$value,$col,$row)
{
	$value = htmlspecialchars(stripslashes($value),ENT_QUOTES);
	return "<textarea name='$name' cols='$col' rows='$row'>$value</textarea>";
}

function inputSubmit($value="Submit",$handler="") {
	$value = htmlVal($value);
	$h = ($handler == "") ? "" : " $handler";
	return "<input type='submit' value='$value'$h>";
}

function inputReset($value="Reset",$handler="") {
	$value = htmlVal($value);
	$h = ($handler == "") ? "" : " $handler";
	return "<input type='reset' value='$value'$h>";
}

function inputButton($value,$handler) {
	$value = htmlVal($value);
	$h = ($handler == "") ? "" : " $handler";
	return "<input type='button' value='$value'$h>";
}

function inputCheckBox($name,$value,$checked="") {
	$value = htmlVal($value);
	$c = ($checked == "") ? "" : " checked";
	return "<input type='checkbox' name='$name' value='$value'$c>";
}

function inputRadio($name,$value,$checked)
{
	$value = htmlVal($value);
	$c = ($checked == "") ? "" : " checked";
	return "<input type='radio' name='$name' value='$value'$c>";
}

function inputCheckAll()
	{ return "<input type='checkbox' onClick='checkAllBoxes(this.form)'>"; }

function startSelect($name,$value="",$handler="")
{
	return "<select id='$name' name='$name'>";
}

function endSelect() { return "</select>"; }

# dateCollector:
# - returns HTML to render pop-up calendar for choosing dates

function dateCollector($name,$default="",$withTime=false)
{
	if (!def($default)) $default = date("Y-m-d",time());
	$default_show = dateView($default);
	$html = "<input type='hidden' name='$name' id='${name}_id' ".
		" value='$default'>".
		"<span class='formDate' id='${name}_show'>".
		"$default_show</span> ".
		"&nbsp; <img src='".URL."/img/cal.png' ".
		"id='${name}_b' style='cursor:pointer'/> ".
		sp().hint("(Must fill this field via calendar)");
	return array($html,"",calSetup($name,$withTime));
}

# calSetup:
# - Javascript to set up the calendars (on page load)
function calSetup($field,$withTime=false)
{
return <<< JAVASCRIPT
Calendar.setup({
inputField  : "${field}_id",
ifFormat    : "%Y-%m-%d",
displayArea : "${field}_show",
daFormat    : "%a %d %b %Y",
button      : "${field}_b",
weekNumbers : false
});
JAVASCRIPT;
}

# timeCollector:
# - returns HTML for pop-ups to select time-of-day (15 min resolution)

function timeCollector($name,$default="")
{
	if (!$default) $default = date("H:M",time());
	list($def_hour,$def_min) = split(":",$default);
	$html = "";
	$html .= "<select name='${name}_hour'>";
	for ($i = 0; $i < 24; $i++) {
		$sel = ($i != $def_hour) ? "" : " selected";
		$html .= "<option$sel value='$i'>".sprintf("%02d",$i);
	}
	$html .= "</select>:<select name='${name}_month'>";
	for ($i = 0; $i < 60; $i += 15) {
		$sel = ($i != $def_min) ? "" : " selected";
		$html .= "<option$sel value='$i'>".sprintf("%02d",$i);
	}
	$html .= "</select>\n";
	return $html;
}

# selectFromRange:
# - builds a select query based on a range of integers

function selectFromRange($name,$selected,$lo,$hi)
{
	$html = "<select id='$name' name='$name'>\n";
	for ($i = $lo; $i <= $hi; $i++) {
		if ($i == $selected)
			$sel = " selected";
		else
			$sel = "";
		$html .= "<option value='$i'$sel>$i\n";
	}
	$html .= "</select>\n";
	return $html;
}

# selectFromList:
# - builds a select query based on an array of key=>val

function selectFromList($name,$selected,$list,$style="",$events="")
{
	$sty = ($style == "") ? "" : " style='$style'";
	$eve = ($events == "") ? "" : " $events";
	$html = "<select id='$name' name='$name'$sty$eve>\n";
	foreach ($list as $key => $val) {
      //echo $val."<br/>";
      $num = explode(" ",$val);
      //echo $num[0];
      //echo $selected;
		if ($num[0] == $selected) {
         //echo $num[0];
         //echo $selected;
			$sel = " selected";
		} else {
			$sel = "";
      }
		//$html .= "<option value='$val'$sel>$key\n";
      $html .= "<option value='$num[0]'$sel>Question $val\n";
	}
	$html .= "</select>\n";
	return $html;
}

# selectByQuery:
# - builds a <select>...</select> with options derived from a query

function selectByQuery($name,$selected,$db,$query,$any=false,$add=false)
{
	$a = $add ? " onChange='toggleAddInput($name,${name}_x);'" : "";
	$html = "<select id='$name' name='$name'$a>\n";
	if ($any) {
		$s = ($selected == "[Any]") ? " selected" : "";
		$html .= "<option value='[Any]'$s>[Any]</option>\n";
		
	}
	if (!def($selected))
		$html .= "<option value=''></option>";
	$r = dbQuery($db,$query);
	while ($t = dbNext($r)) {
		if (!def($t[0])) continue;
		$s = ($t[0] == $selected) ? " selected" : "";
		$html .= "<option value='$t[0]'$s>$t[1]</option>\n";
	}
	if ($add) {
		$t = "Other - please specify :";
		$html .= "<option value='[Other]'>$t</option>\n";
	}
	$html .= "</select>\n";
	if ($add) {
		$html .= "<input type='text' id='${name}_x' ".
			 "name='${name}_x' style='display:none'>";
	}
	return $html;
}

# linkedSelect:
# - returns a selector that determines options of another selector

function linkedSelect($name1,$val1,$name2,$val2,$db,$query)
{
	$opts = array();
	$r = dbQuery($db,$query);
	while ($t = dbNext($r)) {
		if (!def($t[0]) || !def($t[1])) continue;
		$k1 = $t[0]; $k2 = $t[1];
		if (!array_key_exists($k1,$opts)) $opts[$k1] = array();
		$opts[$k1][] = $k2;
	}
	$jsdefs = "<script type='text/javascript'>\n";
	$jsdefs .= "var ${name1}_opts = new Array(".count($opts).");\n";
	$i = 0; $opts1 = array(); $other = null;
	foreach ($opts as $opt => $subopts) {
		$arr = "new Array(\"$opt\",\"".join('","',$subopts)."\");\n";
		if ($opt == "Other") { $other = $arr; continue; }
		$jsdefs .= "${name1}_opts[$i] = $arr";
		$opts1[$opt] = $opt;
		$i++;
	}
	if (def($other)) {
		$jsdefs .= "${name1}_opts[$i] = $other";
		$opts1["Other"] = "Other";
	}
	$jsdefs .= "</script>\n";
	$onChange = "linkedSelect(\"$name1\",\"$name2\",${name1}_opts);";
	$html = selectFromList($name1,$val1,$opts1,"","onChange='$onChange'");
	return array($html,$jsdefs,$onChange);
}

# selectBySearch:
# - set up a field to hold value returned by search
#   and a button to invoke the search in a pop-up window

function selectBySearch($name,$idval,$value,$searchURL)
{
	$js   = "var popup = window.open('$searchURL','unitSearch',".
		"'scrollbars=yes,resizable=yes,width=600,height=400');".
#		"'width=600,height=400,scrollbars=1,resizeable=1,".
#		"toolbar=0,menubar=0,status=0');".
		"popup.focus();".
		"return false;";
	$idv = htmlspecialchars($idval,ENT_QUOTES);
	$v = htmlspecialchars($value,ENT_QUOTES);
	$html =	"<a href='$searchURL' onClick=\"$js\" target='unitSearch'>".
		"<button><small>Search</small></button></a>&nbsp;".
		"<input type='hidden' name='$name' value='$idv'>".
		"<input type='text' readonly ".
		"name='${name}_shown' value='$v' size=30>".
		sp().hint("(Must fill this field by searching)");
	return $html;
}

# valueView: convert $value of $type to displayed form

function valueView($value, $type)
{
	switch ($type) {
	case "date":  return dateView($value); break;
	case "money": return dollarView($value); break;
	default:      return $value; break;
	}
}

# formFields:
# - takes a specification of form fields
# - returns (HTML,JSdefs,JSinit) to render the form as a table
# - doesn't include <form>...</form>
#   - this is supplied separately for flexibility (e.g. extra fields)
# - the specification is an array of elements of the form
#   label => array(status, type, value, generator)
#            status = "ro"(read-only), "rw"(read-write)
#            name   = name of CGI parameter for this field
#            type   = select|search|text|string|date|time|integer|...
#            value  = current value (null if no current value)
#            val2   = printable value OR db handle (for "select") OR hint
#            gen    = query/code to generate set of values ("select"), OR
#                     URL of page to find/select value ("search")

function formFields($fields)
{
	$html = ""; $jsdefs = ""; $jsinit = "";
	$ndates = $nlinked = $ntoggles = 0;
	foreach ($fields as $label => $f)
	{
		$errmsg = ""; $length = 20; $height = 3; $width = 50;
		# var_dump($finfo); echo "<br>\n";
		# $status = $finfo[0]; $pname = $finfo[1];
		# $type = $finfo[2]; $value = $finfo[3];
		list($status,$pname,$type,$value) = $f;
		if (preg_match('/^string:/',$type))
			list($type,$length) = explode(':',$type);
		elseif (preg_match('/^text:/',$type))
			list($type,$height,$width) = explode(':',$type);
		$hasErr = false;
		if (preg_match('/^ERR:/',$value)) {
			$hasErr = true;
			list($x,$val,$errmsg) = explode(':',$value);
			$value = htmlspecialchars(urldecode($val));
		}
		$html .= "<tr valign='top'>";
		if ($hasErr) $label = red($label);
		$html .= "<td align='right'><b>$label</b></td>";
		if ($status == "ro") {
			if (def($value))
				$value = valueView($value,$type);
			else {
				if ($type == "text")
					$value = gray("(none)");
				else
					$value = gray("(unknown)");
			}
			$html .= "<td>$value</td>";
		}
		else {
			$html .= "<td>";
			switch ($type) {
			case "checkbox":
				$c = ($value == 't') ? " checked" : "";
				$html .= "<input type='checkbox' ".
					 "name='$pname' ".
					 "value='t'$c>";
				if (count($f) == 5)
					$html .= sp().hint($f[4]);
				break;
			case "string":
				$v = htmlspecialchars($value,ENT_QUOTES);
				$html .= "<input type='text' ".
					 "name='$pname' ".
					 "value='$v' ".
					 "size='$length' ".
					 "maxlen='$length'>\n";
				if (count($f) == 5)
					$html .= sp().hint($f[4]);
				break;
			case "text":
				$html .= "<textarea name='$pname' ".
					 "rows='$height' ".
					 "cols='$width'>$value".
					 "</textarea>\n";
				if (count($f) == 5)
					$html .= br().hint($f[4]);
				break;
			case "passwd":
				$html .= "<input type='password' ".
					 "name='$pname' ".
					 "value='$v' ".
					 "size='$length' ".
					 "maxlen='$length'>\n";
				break;
			case "money":
				$v = sprintf("%0.2f",$value);
				$html .= "\$<input type='text' ".
					 "style='text-align:right;' ".
					 "name='$pname' ".
					 "value='$v' ".
					 "size='10' ".
					 "maxlen='10'>\n";
				break;
			case "date":
				list($h,$d,$i) = dateCollector($pname,$value);
				$html .= $h; $jsinit .= $i;
				if ($ndates == 0) {
					$jsdefs .= jsUseCalendar();
					$ndates++;
				}
				break;
			case "time":
				$html .= timeCollector($pname,$value);
				break;
			case "tstamp":
				list($h,$d,$i) = dateCollector($pname,$value);
				$html .= $h; $jsinit .= $i;
				if ($ndates == 0) {
					$jsdefs .= jsUseCalendar();
					$ndates++;
				}
				break;
			case "select":
				$html .= selectByQuery($pname,$value,
							$f[4],$f[5]);
				break;
			case "select+add":
				$html .= selectByQuery($pname,$value,$f[4],
							$f[5],false,true);
				if ($ntoggles == 0) {
					$jsdefs .= jsToggleAddInput();
					$ntoggles++;
				}
				break;
			case "linkedSelect":
				list($h,$d,$i) =
					linkedSelect($pname,$value,$f[4],
							$f[5],$f[6],$f[7]);
				$html .= $h; $jsdefs .= $d; $jsinit .= $i;
				if ($nlinked == 0) {
					$jsdefs .= jsLinkedSelect();
					$nlinked++;
				}
				break;
			case "search":
				$id = $value; $value = $f[4];
				$html .= selectBySearch($pname,$id,
							$value,$f[5]);
				break;
			default:
				$html .= "???";
			}
			if ($errmsg != "") {
				$s = "color:red;font-size:small";
				$v = "";
				if (def($value) && $type != "text")
					$v = "\"$value\": ";
				$html .= "<br><span style='$s'>$v".
						ucfirst($errmsg)."</span>";
			}
			$html .= "</td>";
		}
		$html .= "</tr>\n";
	}
	return array($html,$jsdefs,$jsinit);
}

# formPost:
# - perform post-processing for forms
# - primarily required to handle forms with Calendars

function formPost($fields)
{
	$html = "";
	foreach ($fields as $label => $finfo)
	{
		$status = $finfo[0]; $pname = $finfo[1]; $type = $finfo[2];
		if ($status != "ro") {
			switch ($type) {
			case "date":
				$html .= calSetup($pname);
				break;
			case "tstamp":
				$html .= calSetup($pname);
				break;
			}
		}
	}
	return $html;
}
?>
